package org.roger.search;

import java.io.IOException;
import java.util.Iterator;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.search.Collector;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopFieldDocs;
import org.apache.lucene.util.BytesRef;
import org.roger.similarity.BoostingSimilarity;
import org.roger.util.IndexReaderUtil;

public abstract class LuceneSearchBase {
	
	private IndexSearcher searcher;
	
	public static IndexReader getReader(String indexPath){
		return IndexReaderUtil.getIndexReader(indexPath);
	}
	
	public void showDoc(TopDocs results,IndexSearcher searcher){
		int numTotalHits = results.totalHits;
		System.out.println(numTotalHits + " total matching documents");
		
		ScoreDoc[] hits = results.scoreDocs;
		
		for(ScoreDoc hit : hits){
			try {
				Document doc = searcher.doc(hit.doc);
				System.out.println("------------------------------");
				System.out.println("docId:"+hit.doc);
				Iterator<IndexableField> it = doc.iterator();
				while(it.hasNext()){
					IndexableField field = it.next();
					String filed = field.name();
					String content = doc.get(filed);
					if(content != null){
						System.out.println(filed +":" + new String(content.getBytes(),"UTF-8"));
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			System.out.println("score:"+hit.score);	
			
//			try {
//				
//				//Fields fields = searcher.getIndexReader().getTermVectors(hit.doc);
//				//Terms terms = fields.terms("contents");
//				//统计每个doc中，fields为contents的项的名称和频率
//				Terms terms = searcher.getIndexReader().getTermVector(hit.doc, "contents");
//				TermsEnum te = terms.iterator(null);
//				BytesRef text;
//				System.out.println("##############文档"+hit.doc+"#############");
//				while((text = te.next()) != null){
//					System.out.println("项"+text.utf8ToString()+"    频率："+te.totalTermFreq());
//				}
//				
//			} catch (IOException e) {
//				e.printStackTrace();
//			}
		}
	}
	
	public void showDoc(TopFieldDocs results,IndexSearcher searcher){
		int numTotalHits = results.totalHits;
		System.out.println(numTotalHits + " total matching documents");
		
		ScoreDoc[] hits = results.scoreDocs;
		SortField[] sortfields = results.fields;
		for(SortField sortfield : sortfields){
			if(sortfield.getField() != null)
				System.out.println("Sort fields : "+sortfield.getField()+"   ");
			else
				System.out.println("Sort fields : "+sortfield.getType()+"   ");
		}
		
		for(ScoreDoc hit : hits){
			try {
				Document doc = searcher.doc(hit.doc);
				System.out.println("------------------------------");
				System.out.println("docId:"+hit.doc);
				Iterator<IndexableField> it = doc.iterator();
				while(it.hasNext()){
					IndexableField field = it.next();
					String filed = field.name();
					String content = doc.get(filed);
					if(content != null){
						System.out.println(filed +":" + content);
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void explainDoc(TopDocs results,IndexSearcher searcher){
		System.out.println("---------------explain---------------");
		for(ScoreDoc hit : results.scoreDocs){
			try {
				Explanation explain = searcher.explain(getSearchQuery(), hit.doc);
				System.out.println(explain);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 得到查询的Query
	 * @return
	 */
	public abstract Query getSearchQuery();
	/**
	 * 得到搜索的Filter
	 * @return
	 */
	public abstract Filter getFilter();
	/**
	 * 得到排序的Sort
	 * @return
	 */
	public abstract Sort getSort();
	
	public TopDocs search(String indexPath) throws IOException{
		IndexReader reader = getReader(indexPath);
		TopDocs results;
		Query query = getSearchQuery();
		Filter filter = getFilter();
		Sort sort = getSort();
		this.searcher = new IndexSearcher(reader);
		BoostingSimilarity similarity = new BoostingSimilarity();
		searcher.setSimilarity(similarity);
		
		if(sort == null){
			results = searcher.search(query,filter,10);
			showDoc(results,searcher);
			explainDoc(results,searcher);
		}else{
			results = searcher.search(query,filter,10,sort);
			showDoc((TopFieldDocs)results,searcher);
			explainDoc((TopFieldDocs)results,searcher);
		}
		return results;
	}
	
	public void search(String indexPath,Collector collector) throws IOException{
		IndexReader reader = getReader(indexPath);
		Query query = getSearchQuery();
		Filter filter = getFilter();
		this.searcher = new IndexSearcher(reader);
		searcher.search(query, filter, collector);
	}

	public IndexSearcher getSearcher() {
		return this.searcher;
	}
	
	
}
